package io.wjc.config;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

/**
 * 资源服务的自动装配类，这里可以引入一个配置类（使用@EnableConfigurationProperties），动态配置某些属性
 * @see @EnableOauthResourceServer
 */
@Slf4j
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) //这个注解放到@EnableOauthResourceServer里面不生效，没有加载InfrastructureAdvisorAutoProxyCreator类，有兴趣的研究下
@ConditionalOnMissingBean(TokenStore.class)
public class OauthResourceServerAutoConfiguration extends ResourceServerConfigurerAdapter {

	@Value("${spring.application.name}")
	private String RESOURCE_ID;
	/**
	 * 默认资源服务安全配置，可以通过
	 *
	 * @param http
	 */
	@Override
	@SneakyThrows
	public void configure(HttpSecurity http) {
		http
				.authorizeRequests()
				.antMatchers("/**").authenticated()
//				.antMatchers("/**").access("#oauth2.hasScope('read')")
				.and().csrf().disable()
				.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
	}

	@Override
	public void configure(ResourceServerSecurityConfigurer resources) {
		resources
//				.authenticationEntryPoint(resourceAuthExceptionEntryPoint) //配置auth fail point
//				.accessDeniedHandler(accessDeniedHandler) //配置token验证失败信息
//				.tokenServices(tokenService()) //配置token验证服务，jwt token不需要配置
				.resourceId(RESOURCE_ID) //资源 ID，这里取app name
//				.tokenStore(tokenStore()) //token管理器
				.stateless(true)
		;
	}

	@Bean
	@Primary
	@LoadBalanced
	@ConditionalOnMissingBean(RestTemplate.class)
	public RestTemplate lbRestTemplate() {
		RestTemplate restTemplate = new RestTemplate();
		restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
			@Override
			@SneakyThrows
			public void handleError(ClientHttpResponse response) {
				if (response.getRawStatusCode() != HttpStatus.BAD_REQUEST.value()) {
					super.handleError(response);
				}
			}
		});
		return restTemplate;
	}

	/**
	 * 资源服务令牌解析服务，此例中因为使用的是基于客户端的jwt token所以这个类用不到
	 */
    @Bean
    public ResourceServerTokenServices tokenService() {
        //使用远程服务请求授权服务器校验token,必须指定校验token 的url、client_id，client_secret
        RemoteTokenServices service=new RemoteTokenServices();
        service.setCheckTokenEndpointUrl("http://localhost:8085/oauth/check_token");
        service.setClientId("wnApp");
        service.setClientSecret("123456");

        //用户信息token转换器，这种token是默认的token方式，没有增强，如果使用jwt增强了的token，使用JwtAccessTokenConverter转换器
		//DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
		//accessTokenConverter.setUserTokenConverter(userTokenConverter);

		//service.setRestTemplate(lbRestTemplate());
		//service.setAccessTokenConverter(accessTokenConverter);

        return service;
    }


}
